# -*- coding:utf-8 -*-

from django.http import JsonResponse

import redis

class MiddlewareMixin(object):
    """
    中间件
    中间件中的几个方法也是固定的写法
    def process_request(self,request):
        # 无返回值则继续执行
        # 有返回值 直接返回不往下执行
        pass
    def process_view(self, request,view_func,view_func_args,view_func_kwargs):
        pass
    def process_exception(self, request,exception):
        pass
    def process_response(self,request,response):
        # 要有返回值
        pass
        return response
    def process_template_response(self,request,response):
        # 要有返回值
        pass
        return response
    """
    def __init__(self,get_response=None):
        self.get_response= get_response
        
        # 派生出来保证基类的方法依然存在
        super().__init__()

    def __call__(self,request):
        """
        该魔法方法主要的作用就是
        让实例化的类可以被直接调用
        @eg:
            class A:
                def __call__(self):
                    return 'aa'
            a = A()
            a() // 会打印 ==> 'aa'
        """
        response = None
        if hasattr(self,'process_request'):
            # 中间件执行的流程
            response = self.process_request(request)
        if not response:
            response = self.get_response(request)
        if hasattr(self,'process_response'):
            response = self.process_response(request,response)
        return response


class MiddlewareTest1(MiddlewareMixin):
    """
    测试中间件
    """
    def process_request(self,request):
        # 请求的时候处理
        print('m1.process_request',request.COOKIES.get('a'),request.session.get('is_login'))        
    
    def process_response(self,request,response):
        # 响应的时候处理
        # if hasattr(response,'set_cookie'):
        response.set_cookie('a','123')
        print('m1.process_response')
        return response

class MiddlewareTest2(MiddlewareMixin):
    """
    测试中间件
    Session 的储存机制，引擎指定的是redis 
    简单的来说就是K-V的操作，通过用户的信息来做K的键来区分不同的用户，取出的V的值来判断用户是否登录过期
    如果过期的就不让他登录，过期的机制就是redis的expire
    Django的session认证机制就是运用了上方的方法实现的状态保持
    而登录注册的机制就是把数据存到数据库时候对数据做一个加盐加密处理而已

    后台的使用可以考虑使用中间件来完成统一的鉴权
    """
    def process_request(self,request):
        # cookie 使用中间件来测试，基本很少使用中间件来处理cookie 登录，
        # 一般使用session ,Django 内置的有session 和auth登录和认证的中间件
        print('m2.process_request',request.COOKIES.get('a'))
    
    def process_response(self,request,response):
        print('m2.process_response')
        return response

class CheckOnclickMiddleware(object):

    def __init__(self, get_response):
        self.get_response = get_response
        self.poll =  redis.ConnectionPool(host='127.0.0.1',db=1)
        self.redis = redis.Redis(connection_pool=self.poll)
        super().__init__()

    def __call__(self, request):
        """
        __call__ 里面来处理
        """
        source_ip = request.META.get('REMOTE_ADDR')
        print("访问的次数:{count}".format(count=self.redis.llen(source_ip)))
        if self.redis.llen(source_ip) >10:
            return JsonResponse({'message':'访问次数太多了'})
        self.redis.rpush(source_ip,'1')
        self.redis.expire(source_ip, 60)
        return self.get_response(request)
